﻿using FilterIllegalCharacter.Core;
using Flurl.Http;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
using Xceed.Document.NET;
using Xceed.Words.NET;

namespace FilterIllegalCharacter.UI
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        // 任务取消令牌
        private CancellationTokenSource? _cts;
        // 当前窗口关闭状态
        private bool _isClose = false;
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // 绑定进度条处理事件
            FilterHelper.Instance.ProgressBarEvent = ProgressBarLoad_Handle;
        }
        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (_cts != null && !_cts.IsCancellationRequested)
            { 
                MessageBoxResult result = MessageBox.Show("当前还有任务未执行完毕，确定要关闭吗？", "关闭确认", MessageBoxButton.YesNo, MessageBoxImage.Question);

                if (result == MessageBoxResult.Yes)
                {
                    // 此时不关闭窗口，给一个状态等待任务结束后关闭
                    _isClose = true;
                    _cts.Cancel();
                }
                // 取消窗口关闭事件
                e.Cancel = true;
            }
        }

        /// <summary>
        /// 文件拖入事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Grid_Drop(object sender, DragEventArgs e)
        {
            if (btnSelectWordFile.IsEnabled && e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                // 获取拖放的文件列表
                string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
                // 处理单个文件（假设只拖放了一个）
                if (files.Length == 1 && files[0].IsWordDocument())
                {
                    string filePath = files[0];
                    // 在这里处理文件
                    textBoxWordFilePath.Text = filePath;
                }
                else
                {
                    MessageBox.Show("请拖放正确的word文件");
                }
            }
        }
        /// <summary>
        /// 选择word文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSelectWordFile_Click(object sender, RoutedEventArgs e)
        {
            // 创建文件选择对话框实例
            OpenFileDialog openFileDialog = new OpenFileDialog();

            // 设置对话框属性
            openFileDialog.Filter = "Word文档 (*.doc,*.docx)|*.docx"; // 设置文件过滤器
            openFileDialog.FilterIndex = 1;
            openFileDialog.RestoreDirectory = true;

            // 显示对话框
            bool? result = openFileDialog.ShowDialog();

            // 判断是否点击了确定按钮
            if (result == true)
            {
                // 获取选中的文件路径
                string filePath = openFileDialog.FileName;
                // 处理文件
                if (filePath.IsWordDocument())
                {
                    textBoxWordFilePath.Text = filePath;
                }
                else
                {
                    MessageBox.Show("请选择正确的word文件");
                }
            }
        }

        /// <summary>
        /// 开始按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStart_Click(object sender, RoutedEventArgs e)
        {
            // 清空上一次结果
            textBlockResultView.Inlines.Clear();
            double oldMaximum = this.progressBar.Maximum;
            // 获取选定的文件路径
            string wordFilePath = textBoxWordFilePath.Text;
            string newWordFilePath = string.Empty;
            // 确保word文件存在
            if (!File.Exists(wordFilePath))
            {
                MessageBox.Show("请确认是否已选择word文件，或者文件是否存在");
                return;
            }
            else
            {
                // 复制一个新的文件来操作
                newWordFilePath = FileBackup(wordFilePath);
            }
            // 初始化任务取消令牌
            _cts = new CancellationTokenSource();
            // 开启异步任务，此处是耗时操作，需要开启异步执行避免界面假死
            Task.Run(() =>
            {
                try
                {
                    this.Dispatcher.Invoke(() =>
                    {
                        this.progressBar.Maximum = 201;
                    });
                    using (var document = DocX.Load(newWordFilePath))
                    {
                        // 这里不能使用document.Text的字符串当作全文索引，分段以后有些特殊字符导致全文索引和分段索引对不上
                        // 所以取所有分段的文本拼接起来
                        //var rNodeList = FilterHelper.Instance.GetRNodeList(_cts.Token, document.Text);
                        var rNodeList = FilterHelper.Instance.GetRNodeList(_cts.Token, string.Join("", document.Paragraphs.Select(item => item.Text)));
                        // 此处计算关键字命中次数
                        var hitCountList = rNodeList.Select(item => item.text).GroupBy(s => s)
                                               .Select(g => new Tuple<string, int>(g.Key, g.Count()))
                                               .OrderByDescending(s => s.Item2)
                                               .ThenBy(s => s.Item1)
                                               .ToList();
                        // 根据索引和长度高亮文本
                        document.HighlightText(rNodeList, Highlight.red, ProgressBarLoad_Handle);
                        //document.HighlightText(rNodeList, Highlight.red, ProgressBarLoad_Handle);
                        UpdateBlockResultView(hitCountList);
                        // 保存修改后的文档
                        document.Save();
                    }
                    MessageBox.Show("标记完成");
                    OpenWordDocument(newWordFilePath);
                }
                catch (OperationCanceledException)
                {
                    if (File.Exists(newWordFilePath))
                    {
                        File.Delete(newWordFilePath);
                    }
                    MessageBoxResult result = MessageBox.Show("任务已终止");
                    if (result == MessageBoxResult.OK && _isClose)
                    {
                        //关闭窗口
                        this.Dispatcher.Invoke(() =>
                        {
                            this.Close();
                        });
                    }
                }
                catch (Exception ex)
                {
                    if (File.Exists(newWordFilePath))
                    {
                        File.Delete(newWordFilePath);
                    }
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    _cts.Cancel();
                    ProgressBarLoad_Handle(this, 201);
                    this.Dispatcher.Invoke(() =>
                    {
                        this.progressBar.Maximum = oldMaximum;
                    });
                }
            }, _cts.Token);
        }

        public void OpenWordDocument(string filePath)
        {
            try
            {
                ProcessStartInfo startInfo = new ProcessStartInfo(filePath)
                {
                    UseShellExecute = true // 使用操作系统shell启动进程
                };
                Process.Start(startInfo);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"无法打开文档。错误信息: {ex.Message}");
            }
        }
        private void UpdateBlockResultView(List<Tuple<string, int>> hitCountList)
        {
            if (hitCountList.Count > 0)
            {
                // 如果有命中关键字，需要将命中次数显示在界面上
                this.Dispatcher.Invoke(() =>
                {
                    foreach (var hitCount in hitCountList)
                    {
                        // 准备渲染关键字命中次数到界面
                        this.textBlockResultView.Inlines.Add(new System.Windows.Documents.Run(hitCount.Item1) { FontSize = 16, Background = new SolidColorBrush(Colors.LightBlue) });
                        this.textBlockResultView.Inlines.Add(new System.Windows.Documents.Run($"×{hitCount.Item2}    ") { FontSize = 16 });
                    }
                });
            }
        }
        private string FileBackup(string wordFilePath)
        {
            string? directory = Path.GetDirectoryName(wordFilePath);
            string fileName = Path.GetFileNameWithoutExtension(wordFilePath);
            string extension = Path.GetExtension(wordFilePath);
            string timestamp = DateTimeOffset.Now.ToUnixTimeSeconds().ToString();
            // 复制一个新的文件来操作
            string newWordFilePath = $"{directory}\\{fileName}-{timestamp}{extension}";
            File.Copy(wordFilePath, newWordFilePath, true);
            return newWordFilePath;
        }

        /// <summary>
        /// 进度条处理事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="progress"></param>
        private void ProgressBarLoad_Handle(object? sender, double progress)
        {
            this.Dispatcher.Invoke(() =>
            {
                // 这里要控制进度条刷新的频率，不然界面会卡顿，如果0.1还是卡，需要将数字再调大
                double refreshRate = 0.1;
                if (progressBar.Visibility == Visibility.Visible && progress - progressBar.Value >= refreshRate)
                {
                    // 给进度条进度值
                    progressBar.Value = progress;
                }
                if (progress == 0)
                {
                    BtnEnabled(false);
                    progressBar.Value = 0;
                    // 如果进度值是0,则需要显示进度条
                    progressBar.Visibility = Visibility.Visible;
                }
                else if (progress >= this.progressBar.Maximum)
                {
                    BtnEnabled(true);
                    // 否则进度条满了隐藏进度条
                    progressBar.Visibility = Visibility.Hidden;
                }
            });
        }
        /// <summary>
        /// 按钮禁用
        /// </summary>
        /// <param name="flag"></param>
        private void BtnEnabled(bool flag)
        {
            btnLocalDictMgt.IsEnabled = flag;
            btnRemoteDictSycn.IsEnabled = flag;
            btnSelectWordFile.IsEnabled = flag;
            btnStart.IsEnabled = flag;
        }

        /// <summary>
        /// 路径框拖拽事件处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void textBoxWordFilePath_Drop(object sender, DragEventArgs e)
        {
            e.Handled = true;
        }

        /// <summary>
        /// 本地词库维护按钮点击
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnLocalDictMgt_Click(object sender, RoutedEventArgs e)
        {
            Window mainWindow = Application.Current.MainWindow;
            var localDictMgt = new LocalDictMgt();
            localDictMgt.Owner = mainWindow;
            localDictMgt.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            var result = localDictMgt.ShowDialog();
            if (result == true) 
            {
                MessageBox.Show("保存成功");
            }
        }
        /// <summary>
        /// 远程词库同步按钮点击
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRemoteDictSycn_Click(object sender, RoutedEventArgs e)
        {
            _cts = new CancellationTokenSource();
            Task.Run(async () =>
            {
                try
                {
                    ProgressBarLoad_Handle(this, 0d);
                    var urlList = ConfigurationHelper.AppSettings.RemoteDictUrl;
                    if (urlList == null || urlList.Count <= 0)
                    {
                        throw new Exception("请配置远程词库地址");
                    }
                    ProgressBarLoad_Handle(this, 10d);
                    var wordList = new List<string>();
                    // 多个url排队请求
                    for (int i = 0; i < urlList.Count; i++)
                    {
                        string url = urlList[i];
                        // 获取远程词库返回字符串
                        var resultWords = await url.GetStringAsync(cancellationToken: _cts.Token);
                        var remoteWords = resultWords.Split("\r\n").ToList();
                        wordList.AddRange(remoteWords);
                        if (_cts.Token.IsCancellationRequested)
                        {
                            _cts.Token.ThrowIfCancellationRequested();
                        }
                        ProgressBarLoad_Handle(this, (i + 1) * 80d / urlList.Count + 10);
                    }
                    // 将远程词库去重去空后写入本地文件
                    DictFileHelper.WriteRemoteDictFile(wordList.Distinct().Where(x => !string.IsNullOrEmpty(x)).ToList());
                    // 需要重新载入词库到过滤器字典里
                    FilterHelper.Instance.ReInitDictionary(DictFileHelper.ReadAllDictFile());
                    ProgressBarLoad_Handle(this, 100d);
                    MessageBox.Show("同步成功");
                }
                catch (OperationCanceledException)
                {
                    MessageBoxResult result = MessageBox.Show("任务已终止");
                    if (result == MessageBoxResult.OK && _isClose)
                    {
                        //关闭窗口
                        this.Dispatcher.Invoke(() =>
                        {
                            this.Close();
                        });
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    _cts.Cancel();
                    ProgressBarLoad_Handle(this, 101);
                }
            }, _cts.Token);
        }
    }
}
